﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AddIn.EA.Architecture.ComponentLogic.ElementModel;

namespace AddIn.EA.Architecture.ComponentLogic.StandardProject.Builders.Service
{
    public class ElementBuilderDataContract : ElementBuilder
    {
        public override void BuildStructure(ComponentLogic.ElementModel.Package viewModel, AddIn.EA.Framework.RepositoryManager templateRepository, BusinessEntityStandardProject itemEntity)
        {
            //Build the main DataContract Element
            BuildDataContractElement(viewModel, templateRepository, itemEntity);
            //Check if any method has the entity as a parameter or return, if so, create the correspondent object (Request/Response).
            //Check the existing of parameter
            BuildDataContractRequestElement(viewModel, templateRepository, itemEntity);
            //Check the existing of return
            BuildDataContractResponseElement(viewModel, templateRepository, itemEntity);
            //Creating the Filter Class.
            BuildDataContractElementFilter(viewModel, templateRepository, itemEntity);
            //Creating the FilterKey Class.
            BuildDataContractElementFilterKey(viewModel, templateRepository, itemEntity);
        }
        public void BuildDataContractElement(ComponentLogic.ElementModel.Package viewModel, AddIn.EA.Framework.RepositoryManager templateRepository, BusinessEntityStandardProject itemEntity)
        {
            //Set DataContract name.
            AddIn.EA.Framework.Package templatePackage = GetTemplatePackage(templateRepository);
            AddIn.EA.Framework.Element templateServiceContractElement = templatePackage.GetElementByName("[entity_name]");

            ComponentLogic.ElementModel.Package dataContractPackage = GetDataContractPackage(viewModel);

            String elementName = templateServiceContractElement.Name.Replace("[entity_name]", itemEntity.Name);

            //Prevent existing item before include
            dataContractPackage.Elements.RemoveAll(it => it.Name.CompareTo(elementName) == 0);

            //Create the Entity Element
            Element dataContractElement = BuildEntityElementFromTemplate(itemEntity, templateServiceContractElement, elementName);

            //Create the Entity Attributes/Properties.
            BindElementProperties(dataContractElement, itemEntity);

            dataContractPackage.Elements.Add(dataContractElement);
        }
        public void BuildDataContractRequestElement(Package viewModel, AddIn.EA.Framework.RepositoryManager templateRepository, BusinessEntityStandardProject itemEntity)
        {
            if (itemEntity.Methods.Exists(it => it.Parameters.IndexOf(itemEntity.Name) != -1))
            {
                AddIn.EA.Framework.Package templatePackage = GetTemplatePackage(templateRepository);
                AddIn.EA.Framework.Element templateRequestElement = templatePackage.GetPackageByName("Request").GetElementByName("[entity_name]Request");

                ComponentLogic.ElementModel.Package dataContractPackage = GetDataContractPackage(viewModel);
                ComponentLogic.ElementModel.Package dataContractRequestPackage = GetViewModelPackage("Request", dataContractPackage, true);

                //Set DataContract name.
                String requestElementName = templateRequestElement.Name.Replace("[entity_name]", itemEntity.Name);

                //Prevent existing item before include
                dataContractRequestPackage.Elements.RemoveAll(it => it.Name.CompareTo(requestElementName) == 0);

                Element requestEntityElement = BuildEntityElementFromTemplate(itemEntity, templateRequestElement, requestElementName);
                requestEntityElement.InheritanceClassName = itemEntity.Name;

                dataContractRequestPackage.Elements.Add(requestEntityElement);
            }
        }
        public void BuildDataContractResponseElement(Package viewModel, AddIn.EA.Framework.RepositoryManager templateRepository, BusinessEntityStandardProject itemEntity)
        {
            if (itemEntity.Methods.Exists(it => it.Return.IndexOf(itemEntity.Name) != -1))
            {
                AddIn.EA.Framework.Package templatePackage = GetTemplatePackage(templateRepository);

                ComponentLogic.ElementModel.Package dataContractPackage = GetDataContractPackage(viewModel);
                ComponentLogic.ElementModel.Package dataContractResponsePackage = GetViewModelPackage("Response", dataContractPackage, true);

                //Get the template element.
                AddIn.EA.Framework.Element templateResponseElement = templatePackage.GetPackageByName("Response").GetElementByName("[entity_name]Response");

                //Set DataContract name.
                String responseElementName = templateResponseElement.Name.Replace("[entity_name]", itemEntity.Name);

                //Prevent existing item before include
                dataContractResponsePackage.Elements.RemoveAll(it => it.Name.CompareTo(responseElementName) == 0);

                Element responseEntityElement = BuildEntityElementFromTemplate(itemEntity, templateResponseElement, responseElementName);
                responseEntityElement.InheritanceClassName = itemEntity.Name;

                dataContractResponsePackage.Elements.Add(responseEntityElement);
            }
        }
        public void BuildDataContractElementFilter(ComponentLogic.ElementModel.Package viewModel, AddIn.EA.Framework.RepositoryManager templateRepository, BusinessEntityStandardProject itemEntity)
        {
            if (itemEntity.HasFilter)
            {
                AddIn.EA.Framework.Package templatePackage = GetTemplatePackage(templateRepository);
                AddIn.EA.Framework.Element templateServiceContractFilterElement = templatePackage.GetPackageByName("Request").GetElementByName("Filtro[entity_name]");

                ComponentLogic.ElementModel.Package dataContractPackage = GetDataContractPackage(viewModel);
                ComponentLogic.ElementModel.Package dataContractRequestPackage = GetViewModelPackage("Request", dataContractPackage, true);

                String elementFilterName = templateServiceContractFilterElement.Name.Replace("[entity_name]", itemEntity.Name);
                //Prevent existing item before include.
                dataContractRequestPackage.Elements.RemoveAll(it => it.Name.CompareTo(elementFilterName) == 0);

                //Build the filter element.
                Element dataContractFilterElement = BuildEntityElementFromTemplate(itemEntity, templateServiceContractFilterElement, elementFilterName);

                foreach (ComponentLogic.StandardProject.PropertyStandardProject itemProerty in itemEntity.Properties.FindAll(it => it.ComposeFilter))
                    dataContractFilterElement.Attributes.Add(CreateElementModelAttribute(itemProerty));

                dataContractRequestPackage.Elements.Add(dataContractFilterElement);
            }
        }
        public void BuildDataContractElementFilterKey(ComponentLogic.ElementModel.Package viewModel, AddIn.EA.Framework.RepositoryManager templateRepository, BusinessEntityStandardProject itemEntity)
        {
            if (itemEntity.HasKeyFilter)
            {
                AddIn.EA.Framework.Package templatePackage = GetTemplatePackage(templateRepository);
                AddIn.EA.Framework.Element templateServiceContractFilterKeyElement = templatePackage.GetPackageByName("Request").GetElementByName("Filtro[entity_name]Chave");

                ComponentLogic.ElementModel.Package dataContractPackage = GetDataContractPackage(viewModel);
                ComponentLogic.ElementModel.Package dataContractRequestPackage = GetViewModelPackage("Request", dataContractPackage, true);

                String elementFilterKeyName = templateServiceContractFilterKeyElement.Name.Replace("[entity_name]", itemEntity.Name);
                //Prevent existing item before include.
                dataContractRequestPackage.Elements.RemoveAll(it => it.Name.CompareTo(elementFilterKeyName) == 0);

                //Build the filter element.
                Element dataContractFilterKeyElement = BuildEntityElementFromTemplate(itemEntity, templateServiceContractFilterKeyElement, elementFilterKeyName);

                foreach (ComponentLogic.StandardProject.PropertyStandardProject itemProerty in itemEntity.Properties.FindAll(it => it.ComposeKey))
                    dataContractFilterKeyElement.Attributes.Add(CreateElementModelAttribute(itemProerty));

                dataContractRequestPackage.Elements.Add(dataContractFilterKeyElement);
            }
        }
        private Framework.Package GetTemplatePackage(Framework.RepositoryManager templateRepository)
        {
            return templateRepository.GetPackageByName("Servico").GetPackageByName("Service").GetPackageByName("DataContract");
        }
        private Package GetDataContractPackage(ComponentLogic.ElementModel.Package viewModel)
        {
            ComponentLogic.ElementModel.Package servicoPackage = GetViewModelPackage("Servico", viewModel, true);
            ComponentLogic.ElementModel.Package servicePackage = GetViewModelPackage("Service", servicoPackage, true);
            ComponentLogic.ElementModel.Package dataContractPackage = GetViewModelPackage("DataContract", servicePackage, true);
            return dataContractPackage;
        }

        public override void Validate()
        {
        }
    }
}
